package pl.lsierant.j2me.bipacz.intervaltimer;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import pl.lsierant.j2me.bipacz.notifications.INotification;
import pl.lsierant.j2me.bipacz.notifications.impl.DefaultNotification;
import pl.lsierant.j2me.bipacz.notifications.impl.NullNotification;
import pl.lsierant.j2me.bipacz.persistent.DeserializationHelper;
import pl.lsierant.j2me.bipacz.persistent.IPersistent;
import pl.lsierant.j2me.bipacz.persistent.PersistentObjectType;
import pl.lsierant.j2me.bipacz.persistent.SerializationHelper;

/**
 * Class defines one interval. Interval has its duration (e.g. 30s).
 * <p>
 * Its also possible to define custom notification methods at begin and end of
 * interval.
 * 
 */
public class Interval implements IPersistent {
    // interval duration in milliseconds
    private long duration;
    // interval name/description
    private String name;

    private INotification startNotify = NullNotification.INSTANCE;
    private INotification endNotify = DefaultNotification.INSTANCE;

    /**
     * Creates interval with specified duration and default notification events.
     * 
     * @param duration
     *            interval duration in milliseconds
     */
    public Interval(long duration) {
        super();
        this.duration = duration;
    }

    /**
     * Creates interval with specified name, duration and default notification
     * events.
     * 
     * @param duration
     *            interval duration in milliseconds
     */
    public Interval(String name, long duration) {
        super();
        this.name = name;
        this.duration = duration;
    }

    /**
     * Creates interval with specified duration and start notification methods.
     * 
     * @param duration
     *            interval duration in milliseconds
     * @param startNotify
     *            notification method invoked when interval begins
     */
    public Interval(String name, long duration, INotification startNotify) {
        super();
        this.name = name;
        this.duration = duration;
        this.startNotify = startNotify;
    }

    /**
     * Creates interval with specified duration and notification methods.
     * 
     * @param duration
     *            interval duration in milliseconds
     * @param startNotify
     *            notification method invoked when interval begins
     * @param endNotify
     *            notification method invoked when interval ends
     */
    public Interval(String name, long duration, INotification startNotify, INotification endNotify) {
        super();
        this.name = name;
        this.duration = duration;
        this.startNotify = startNotify;
        this.endNotify = endNotify;
    }

    // used for persistence only
    public Interval() {
    }

    /**
     * Invoked when interval begins.
     */
    public void onStart() {
        startNotify.run();
    }

    /**
     * Invoked when interval ends.
     */
    public void onEnd() {
        endNotify.run();
    }

    public long getDuration() {
        return duration;
    }

    public String getName() {
        if (name == null) {
            name = (duration / 1000) + " sec.";
        }
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPersistentObjectType() {
        return PersistentObjectType.INTERVAL;
    }

    public void initialize(DataInputStream serializedData) throws IOException {
        DeserializationHelper helper = new DeserializationHelper(serializedData);
        duration = ((Long) helper.readObject()).longValue();
        name = (String) helper.readObject();
        startNotify = ((INotification) helper.readObject());
        endNotify = ((INotification) helper.readObject());
    }

    public void serialize(DataOutputStream out) throws IOException {
        SerializationHelper helper = new SerializationHelper(out, this, 0);
        helper.addField(duration);
        helper.addField(name);
        helper.addField(startNotify);
        helper.addField(endNotify);
    }

    public String toString() {
        return "Interval [duration=" + duration + ", endNotify=" + endNotify + ", name=" + name
                + ", startNotify=" + startNotify + "]";
    }

}
